package com.gitee.jmash.rbac.client.shiro.authc;

import java.security.MessageDigest;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.lang.codec.CodecSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JmashCredentialsMatcher extends CodecSupport implements CredentialsMatcher {


  private static final Logger log = LoggerFactory.getLogger(JmashCredentialsMatcher.class);

  protected Object getCredentials(AuthenticationToken token) {
    return token.getCredentials();
  }


  protected Object getCredentials(AuthenticationInfo info) {
    return info.getCredentials();
  }


  protected boolean equals(Object tokenCredentials, Object accountCredentials) {
    if (null == tokenCredentials && null == accountCredentials) {
      return true;
    }
    if (null == tokenCredentials || null == accountCredentials) {
      return false;
    }
    if (log.isDebugEnabled()) {
      if (tokenCredentials.getClass() != null && accountCredentials.getClass()!= null){
        log.debug(String.format("Performing credentials equality check for tokenCredentials of type [%s] and accountCredentials of type [%s]",tokenCredentials.getClass().getName(),accountCredentials.getClass().getName()));
      }else {
        return false;
      }
    }
    if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
      if (log.isDebugEnabled()) {
        log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing "
            + "array equals comparison");
      }
      byte[] tokenBytes = toBytes(tokenCredentials);
      byte[] accountBytes = toBytes(accountCredentials);
      return MessageDigest.isEqual(tokenBytes, accountBytes);
    } else {
      return accountCredentials.equals(tokenCredentials);
    }
  }


  public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
    Object tokenCredentials = getCredentials(token);
    Object accountCredentials = getCredentials(info);
    return equals(tokenCredentials, accountCredentials);
  }


}
